package com.gitee.fsadmin.service.sys.login.impl;

import com.gitee.fsadmin.common.enums.StatusEnum;
import com.gitee.fsadmin.common.manager.UserCacheManager;
import com.gitee.fsadmin.common.user.User;
import com.gitee.fsadmin.common.util.CopyUtil;
import com.gitee.fsadmin.dao.entity.SysUser;
import com.gitee.fsadmin.service.sys.SysUserService;
import com.gitee.fsadmin.service.sys.login.dto.LoginUser;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.extern.slf4j.Slf4j;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Init;
import org.noear.solon.annotation.Inject;

import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * @author 六如
 */
@Component
@Slf4j
public class DefaultUserCacheManager implements UserCacheManager {

    @Inject
    private SysUserService sysUserService;

    @Inject("${admin.user-cache-timeout-minutes:15}")
    private int timeoutMinutes;

    // key: userId
    private LoadingCache<Long, Optional<User>> userCache;

    @Override
    public User getUser(long userId) {
        return userCache.getUnchecked(userId).orElse(null);
    }

    @Override
    public void saveUser(User user) {
        if (user == null) {
            return;
        }
        userCache.put(user.getUserId(), Optional.of(user));
    }

    private LoadingCache<Long, Optional<User>> buildCache(int timeout) {
        if (timeout <= 0) {
            throw new IllegalArgumentException("timeout must be gt 0");
        }
        CacheBuilder<Object, Object> cacheBuilder = CacheBuilder.newBuilder();
        cacheBuilder.expireAfterAccess(timeout, TimeUnit.MINUTES);
        return cacheBuilder
                .build(new CacheLoader<Long, Optional<User>>() {
                    @Override
                    public Optional<User> load(Long id) throws Exception {
                        User user = getLoginUser(id);
                        return Optional.ofNullable(user);
                    }
                });
    }

    /**
     * 获取登陆用户
     * @param id
     * @return
     */
    private User getLoginUser(long id) {
        SysUser userInfo = sysUserService.getById(id);
        if (userInfo == null) {
            log.warn("登录用户不存在，userId：{}", id);
            return null;
        }
        if (userInfo.getStatus() == StatusEnum.DISABLED.getValue()) {
            log.warn("用户被禁用, userId:{}, username:{}, nickname:{}", userInfo.getId(), userInfo.getUsername(), userInfo.getNickname());
            return null;
        }
        return CopyUtil.copyBean(userInfo, LoginUser::new);
    }

    @Init
    public void afterPropertiesSet() throws Exception {
        userCache = buildCache(timeoutMinutes);
    }

}
